﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace ft_module_parser.aftconversion.ppd
{
    class mass_convert
    {
        public static void Convert(string gamepath = "", string argv = "", string reso = "", string nico = "", string audiobitrate = "500")
        {
            Console.WriteLine("Experimental PPD -> FT Tool v1");
            Console.WriteLine("niconico is not supported.");
            Console.WriteLine("ASCII folder name only.");
            Console.WriteLine();
            Console.WriteLine(textconst.credits);
            Console.WriteLine();

            Bitmap zerobm = new Bitmap(1024, 512);

            if (!Directory.Exists(gamepath + "divamods"))
                Directory.CreateDirectory(gamepath + "divamods");

            if (!Directory.Exists(gamepath + "ppd"))
                Directory.CreateDirectory(gamepath + "ppd");
            
            if (!File.Exists(gamepath + "ppd\\ffmpeg.exe"))
            {
                Console.Write("Download FFMPEG? (Y/N) ");
                
                if (Console.ReadKey().KeyChar.ToString().ToLower() == "y")
                {
                    Console.WriteLine("\nDownloading FFMPEG... (approx. 16MB)");
                    using (var client = new WebClient())
                    {
                       client.DownloadFile("https://github.com/lybxlpsv/ft_parser/releases/download/0.0.1/librot.gepmff", "ppd//librotgepmff");
                    }
                    var librot = File.ReadAllBytes("ppd\\librotgepmff");
                    File.WriteAllBytes("ppd\\ffmpeg.exe", BrotliSharpLib.Brotli.DecompressBuffer(librot, 0, librot.Length));
                    File.Delete("ppd\\librotgepmff");
                }
                else return;
            }
            GC.Collect();
            if (!File.Exists(gamepath + "ppd\\youtube-dl.exe"))
            {
                Console.Write("Download Youtube-DL? (Y/N) ");
                if (Console.ReadKey().KeyChar.ToString().ToLower() == "y")
                {
                    Console.WriteLine("\nDownloading Youtube-DL...");
                    using (var client = new WebClient())
                    {
                        client.DownloadFile("https://yt-dl.org/latest/youtube-dl.exe", "ppd//youtube-dl.exe");
                    }
                }
                else return;
            }

            foreach (string file in Directory.EnumerateFiles(gamepath + "ppd\\", "data.ini", SearchOption.AllDirectories))
            {
                if (gamepath.Count() != 0)
                    gamepath = gamepath + "\\";

                var modini = new List<string>();
                var pvdb = new List<string>();

                string name = "";
                string author = "";
                int ver = 0;
                int pvid = -1;
                string type = "";
                string base_name = "";
                var path = Path.GetDirectoryName(file) + "\\";
                var foldername = Path.GetFileName(Path.GetDirectoryName(file));

                var modbase_name = foldername.Replace(" ", "_");
                if (!Directory.Exists(gamepath + "ppd\\video"))
                    File.Delete(gamepath + "ppd\\video");

                if (!Directory.Exists(gamepath + "ppd\\audio"))
                    File.Delete(gamepath + "ppd\\audio");

                if (!Directory.Exists(gamepath + "ppd\\video.mp4"))
                    File.Delete(gamepath + "ppd\\video.mp4");

                if (!Directory.Exists(gamepath + "ppd\\audio.ogg"))
                    File.Delete(gamepath + "ppd\\audio.ogg");

                if (!Directory.Exists(gamepath + "divamods"))
                    Directory.CreateDirectory(gamepath + "\\divamods");

                if (!Directory.Exists(gamepath + "divamods\\" + foldername))
                    Directory.CreateDirectory(gamepath + "divamods\\" + foldername);

                if (!Directory.Exists(gamepath + "divamods\\" + foldername + "\\script")) ;
                Directory.CreateDirectory(gamepath + "divamods\\" + foldername + "\\script");

                if (!Directory.Exists(gamepath + "divamods\\" + foldername + "\\song"))
                    Directory.CreateDirectory(gamepath + "divamods\\" + foldername + "\\song");

                if (!Directory.Exists(gamepath + "divamods\\" + foldername + "\\movie"))
                    Directory.CreateDirectory(gamepath + "divamods\\" + foldername + "\\movie");

                var modpath = gamepath + "divamods\\" + foldername + "\\";

                bool easy = false;
                bool normal = false;
                bool hard = false;
                bool extreme = false;
                var video = "";

                if (File.Exists(modpath + "\\script\\" + modbase_name + "_easy.dsc"))
                    File.Delete(modpath + "\\script\\" + modbase_name + "_easy.dsc");

                if (File.Exists(modpath + "\\script\\" + modbase_name + "_normal.dsc"))
                    File.Delete(modpath + "\\script\\" + modbase_name + "_normal.dsc");

                if (File.Exists(modpath + "\\script\\" + modbase_name + "_hard.dsc"))
                    File.Delete(modpath + "\\script\\" + modbase_name + "_hard.dsc");

                if (File.Exists(modpath + "\\script\\" + modbase_name + "_extreme.dsc"))
                    File.Delete(modpath + "\\script\\" + modbase_name + "_extreme.dsc");

                var args = new List<string>();
                args.Add(path + "easy.ppd");

                if (File.Exists(path + "easy.ppd"))
                {
                    PPD2DSC ppd = new PPD2DSC();
                    ppd.Convert(args.ToArray());
                    File.Move(path + "easy.dsc", modpath + "\\script\\" + modbase_name + "_easy.dsc");
                    easy = true;
                }

                args.Clear();
                args.Add(path + "normal.ppd");
                if (File.Exists(path + "normal.ppd"))
                {
                    PPD2DSC ppd = new PPD2DSC();
                    ppd.Convert(args.ToArray());
                    File.Move(path + "normal.dsc", modpath + "\\script\\" + modbase_name + "_normal.dsc");
                    normal = true;
                }

                args.Clear();
                args.Add(path + "hard.ppd");
                if (File.Exists(path + "hard.ppd"))
                {
                    PPD2DSC ppd = new PPD2DSC();
                    ppd.Convert(args.ToArray());
                    File.Move(path + "hard.dsc", modpath + "\\script\\" + modbase_name + "_hard.dsc");
                    hard = true;
                }

                args.Clear();
                args.Add(path + "extreme.ppd");
                if (File.Exists(path + "extreme.ppd"))
                {
                    PPD2DSC ppd = new PPD2DSC();
                    ppd.Convert(args.ToArray());
                    File.Move(path + "extreme.dsc", modpath + "\\script\\" + modbase_name + "_extreme.dsc");
                    extreme = true;
                }
                bool dlvideo = true;
                if (File.Exists(modpath + "\\song\\" + modbase_name + ".ogg"))
                    if (File.Exists(modpath + "\\movie\\" + modbase_name + ".mp4"))
                        dlvideo = false;
                string videofile = null;

                if (File.Exists(path + "video.txt"))
                {
                    video = File.ReadAllText(path + "video.txt");
                }

                var avis = Directory.EnumerateFiles(path, "*.avi", SearchOption.AllDirectories);
                if (avis.Count() != 0)
                    videofile = avis.First();

                var mp4s = Directory.EnumerateFiles(path, "*.mp4", SearchOption.AllDirectories);
                if (mp4s.Count() != 0)
                    videofile = mp4s.First();

                if ((videofile != null) && (dlvideo))
                {
                    {
                        File.Copy(videofile, gamepath + "ppd\\video", true);
                        Console.WriteLine("Muxing Existing Video...");
                        {
                            var process = new Process
                            {
                                StartInfo = new ProcessStartInfo
                                {
                                    FileName = "ppd\\ffmpeg.exe",
                                    WorkingDirectory = ".\\ppd",
                                    Arguments = "-v quiet -stats -y -i video -vn -c:a libvorbis -ar 44100 -b:a " + audiobitrate +"k audio.ogg",
                                    UseShellExecute = false,
                                    //RedirectStandardOutput = true,
                                    //RedirectStandardError = true,
                                    CreateNoWindow = true
                                }
                            };
                            process.Start();

                            var process2 = new Process
                            {
                                StartInfo = new ProcessStartInfo
                                {
                                    FileName = "ppd\\ffmpeg.exe",
                                    WorkingDirectory = ".\\ppd",
                                    //Arguments = "-i video -codec copy video.mp4",
                                    //Arguments = "-v quiet -stats -y -hwaccel nvdec -i video -s 1280x720 -c:v h264_nvenc -preset llhq -rc:v vbr_minqp -qmin:v 5 -qmax:v 12 video.mp4",
                                    Arguments = argv,
                                    UseShellExecute = false,
                                    //RedirectStandardOutput = true,
                                    //RedirectStandardError = true,
                                    CreateNoWindow = false
                                }
                            };
                            process2.Start();
                            process.WaitForExit();
                            process2.WaitForExit();
                        }
                        File.Move("ppd\\audio.ogg", modpath + "\\song\\" + modbase_name + ".ogg");
                        File.Move("ppd\\video.mp4", modpath + "\\movie\\" + modbase_name + ".mp4");
                    }
                    dlvideo = false;
                }
                else
                {
                    
                }
                if (dlvideo)
                {
                    if (File.Exists(path + "video.txt"))
                    {
                        video = File.ReadAllText(path + "video.txt");
                    }
                    else
                    {
                        Console.WriteLine(foldername);
                        Console.Write("Youtube Video URL > ");
                        video = Console.ReadLine();
                    }

                    Console.WriteLine("Downloading Video...");
                    {
                        var process = new Process
                        {
                            StartInfo = new ProcessStartInfo
                            {
                                FileName = "ppd\\youtube-dl.exe",
                                WorkingDirectory = ".\\ppd",
                                Arguments = "-f bestaudio " + video + " -o audio",
                                UseShellExecute = false,
                                RedirectStandardOutput = true,
                                RedirectStandardError = true,
                                CreateNoWindow = true
                            }
                        };
                        process.Start();

                        var process2 = new Process
                        {
                            StartInfo = new ProcessStartInfo
                            {
                                FileName = "ppd\\youtube-dl.exe",
                                WorkingDirectory = ".\\ppd",
                                Arguments = "-f " + reso + " " + video + " -o video",
                                UseShellExecute = false,
                                //RedirectStandardOutput = true,
                                //RedirectStandardError = true,
                                CreateNoWindow = false
                            }
                        };
                        process2.Start();
                        process.WaitForExit();
                        process2.WaitForExit();
                    }
                    Console.WriteLine("Muxing Video...");
                    {
                        var process = new Process
                        {
                            StartInfo = new ProcessStartInfo
                            {
                                FileName = "ppd\\ffmpeg.exe",
                                WorkingDirectory = ".\\ppd",
                                Arguments = "-v quiet -stats -y -i audio -vn -c:a libvorbis -ar 44100 -b:a " + audiobitrate + "k audio.ogg",
                                UseShellExecute = false,
                                RedirectStandardOutput = true,
                                RedirectStandardError = true,
                                CreateNoWindow = true
                            }
                        };
                        process.Start();

                        var process2 = new Process
                        {
                            StartInfo = new ProcessStartInfo
                            {
                                FileName = "ppd\\ffmpeg.exe",
                                WorkingDirectory = ".\\ppd",
                                //Arguments = "-i video -codec copy video.mp4",
                                //Arguments = "-v quiet -stats -y -hwaccel nvdec -i video -s 1280x720 -c:v h264_nvenc -preset llhq -rc:v vbr_minqp -qmin:v 5 -qmax:v 12 video.mp4",
                                Arguments = argv,
                                UseShellExecute = false,
                                //RedirectStandardOutput = true,
                                //RedirectStandardError = true,
                                CreateNoWindow = false
                            }
                        };
                        process2.Start();
                        process.WaitForExit();
                        process2.WaitForExit();
                    }
                    try
                    {
                        File.Move("ppd\\audio.ogg", modpath + "\\song\\" + modbase_name + ".ogg");
                    }
                    catch
                    {

                    }

                    try
                    {
                        File.Move("ppd\\video.mp4", modpath + "\\movie\\" + modbase_name + ".mp4");
                    }
                    catch
                    {

                    }
                }

                Bitmap bm0 = new Bitmap(2048, 1024);
                Bitmap source = ytparse.getThumb(video);

                if (source != null)
                {
                    var canvas = Graphics.FromImage(bm0);
                    canvas.CompositingQuality = CompositingQuality.HighQuality;
                    canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    canvas.SmoothingMode = SmoothingMode.HighQuality;
                    {
                        canvas.DrawImage(source, 0, 0, 1283, 723);
                    }
                    {
                        var bmp3 = new Bitmap(504, 504);
                        int width = 504;
                        int height = 504;
                        var canvas2 = Graphics.FromImage(bmp3);

                        // Scaling
                        float scaling;
                        float scalingY = (float)source.Height / height;
                        float scalingX = (float)source.Width / width;
                        if (scalingX < scalingY) scaling = scalingX; else scaling = scalingY;

                        int newWidth = (int)(source.Width / scaling);
                        int newHeight = (int)(source.Height / scaling);

                        // Correct float to int rounding
                        if (newWidth < width) newWidth = width;
                        if (newHeight < height) newHeight = height;

                        // See if image needs to be cropped
                        int shiftX = 0;
                        int shiftY = 0;

                        if (newWidth > width)
                        {
                            shiftX = (newWidth - width) / 2;
                        }

                        if (newHeight > height)
                        {
                            shiftY = (newHeight - height) / 2;
                        }

                        canvas2.DrawImage(source, -shiftX, -shiftY, newWidth, newHeight);
                        canvas.DrawImage(bmp3, 1283, 0, 504, 504);
                    }
                    if (!Directory.Exists(gamepath + "divamods\\" + foldername + "\\thumb"))
                        Directory.CreateDirectory(gamepath + "divamods\\" + foldername + "\\thumb");
                    bm0.RotateFlip(RotateFlipType.RotateNoneFlipY);
                    bm0.Save(modpath + "thumb\\MERGE_D5COMP_0.png", System.Drawing.Imaging.ImageFormat.Png);
                    zerobm.Save(modpath + "thumb\\MERGE_D5COMP_1.png", System.Drawing.Imaging.ImageFormat.Png);
                }

                Console.WriteLine("Generating PV_DB...");
                modini.Add("name=" + foldername);
                modini.Add("type=pv");
                modini.Add("author=unk");
                modini.Add("base_name=" + modbase_name);
                modini.Add("ver=2");
                pvdb.Add("pv_000.bpm=120");
                pvdb.Add("pv_000.chainslide_failure_name=slide_ng03");
                pvdb.Add("pv_000.chainslide_first_name=slide_long02a");
                pvdb.Add("pv_000.chainslide_sub_name=slide_button08");
                pvdb.Add("pv_000.chainslide_success_name=slide_ok03");
                pvdb.Add("pv_000.date=20190101");
                pvdb.Add("pv_000.difficulty.attribute.original=1");
                pvdb.Add("pv_000.difficulty.attribute.slide=1");
                if (easy)
                {
                    pvdb.Add("pv_000.difficulty.easy.0.edition=0");
                    pvdb.Add("pv_000.difficulty.easy.0.level=PV_LV_02_0");
                    pvdb.Add("pv_000.difficulty.easy.0.level_sort_index=50");
                    pvdb.Add("pv_000.difficulty.easy.0.script_file_name=rom/script/" + modbase_name + "_easy.dsc");
                    pvdb.Add("pv_000.difficulty.easy.0.script_format=0x15122517");
                    pvdb.Add("pv_000.difficulty.easy.0.version=1");
                    pvdb.Add("pv_000.difficulty.easy.length=1");
                }
                else
                {
                    pvdb.Add("pv_000.difficulty.easy.length=0");
                }
                pvdb.Add("pv_000.difficulty.encore.length=0");
                if (extreme)
                {
                    pvdb.Add("pv_000.difficulty.extreme.0.edition=0");
                    pvdb.Add("pv_000.difficulty.extreme.0.level=PV_LV_09_0");
                    pvdb.Add("pv_000.difficulty.extreme.0.level_sort_index=50");
                    pvdb.Add("pv_000.difficulty.extreme.0.script_file_name=rom/script/" + modbase_name + "_extreme.dsc");
                    pvdb.Add("pv_000.difficulty.extreme.0.script_format=0x15122517");
                    pvdb.Add("pv_000.difficulty.extreme.0.version=1");
                    pvdb.Add("pv_000.difficulty.extreme.length=1");
                }
                else
                {
                    pvdb.Add("pv_000.difficulty.extreme.length=0");
                }
                if (hard)
                {
                    pvdb.Add("pv_000.difficulty.hard.0.edition=0");
                    pvdb.Add("pv_000.difficulty.hard.0.level=PV_LV_07_0");
                    pvdb.Add("pv_000.difficulty.hard.0.level_sort_index=50");
                    pvdb.Add("pv_000.difficulty.hard.0.script_file_name=rom/script/" + modbase_name + "_hard.dsc");
                    pvdb.Add("pv_000.difficulty.hard.0.script_format=0x15122517");
                    pvdb.Add("pv_000.difficulty.hard.0.version=1");
                    pvdb.Add("pv_000.difficulty.hard.length=1");
                }
                else
                {
                    pvdb.Add("pv_000.difficulty.hard.length=0");
                }
                if (normal)
                {
                    pvdb.Add("pv_000.difficulty.normal.0.edition=0");
                    pvdb.Add("pv_000.difficulty.normal.0.level=PV_LV_05_0");
                    pvdb.Add("pv_000.difficulty.normal.0.level_sort_index=50");
                    pvdb.Add("pv_000.difficulty.normal.0.script_file_name=rom/script/" + modbase_name + "_normal.dsc");
                    pvdb.Add("pv_000.difficulty.normal.0.script_format=0x15122517");
                    pvdb.Add("pv_000.difficulty.normal.0.version=1");
                    pvdb.Add("pv_000.difficulty.normal.length=1");
                }
                else
                {
                    pvdb.Add("pv_000.difficulty.normal.length=0");
                }
                pvdb.Add("pv_000.hidden_timing=0.3");
                pvdb.Add("pv_000.high_speed_rate=4");
                pvdb.Add("pv_000.motion.00=CMN_MRA00_13_01");
                pvdb.Add("pv_000.movie_file_name=rom/movie/" + modbase_name + ".mp4");
                pvdb.Add("pv_000.movie_surface=FRONT");
                pvdb.Add("pv_000.performer.0.chara=MIK");
                pvdb.Add("pv_000.performer.0.pv_costume=1");
                pvdb.Add("pv_000.performer.0.type=VOCAL");
                pvdb.Add("pv_000.performer.num=1");
                pvdb.Add("pv_000.sabi.play_time=50.0");
                pvdb.Add("pv_000.sabi.start_time=25.0");
                pvdb.Add("pv_000.se_name=01_button1");
                pvdb.Add("pv_000.slide_name=slide_se13");
                pvdb.Add("pv_000.slidertouch_name=slide_windchime");
                pvdb.Add("pv_000.song_file_name=rom/sound/song/" + modbase_name + ".ogg");
                pvdb.Add("pv_000.song_name=" + foldername);
                pvdb.Add("pv_000.song_name_reading=" + foldername);
                pvdb.Add("pv_000.songinfo.arranger=unk");
                pvdb.Add("pv_000.songinfo.lyrics=unk");
                pvdb.Add("pv_000.songinfo.music=unk");
                pvdb.Add("pv_000.sudden_timing=0.6");

                File.WriteAllLines(modpath + "\\mod.txt", modini);

                if (!File.Exists(modpath + "\\pv_db.txt"))
                    File.WriteAllLines(modpath + "\\pv_db.txt", pvdb);
            }
        }
    }
}
